/**
 * Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jfinal.kit;

import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import com.jfinal.core.Const;

/**
 * PropKit. PropKit can load properties file from CLASSPATH or File object.
 * 
 * Prop工具类:
 * 从classpath或者文件path加载property文件
 */
public class PropKit {
	
	private static Prop prop = null;
	private static final ConcurrentHashMap<String, Prop> map = new ConcurrentHashMap<String, Prop>();
	
	private PropKit() {}
	
	/**
	 * Using the properties file. It will loading the properties file if not loading.
	 * 加载property文件
	 * @see #use(String, String)
	 */
	public static Prop use(String fileName) {
		return use(fileName, Const.DEFAULT_ENCODING);
	}
	
	/**
	 * Using the properties file. It will loading the properties file if not loading.
	 * <p>
	 * Example:<br>
	 * PropKit.use("config.txt", "UTF-8");<br>
	 * PropKit.use("other_config.txt", "UTF-8");<br><br>
	 * String userName = PropKit.get("userName");<br>
	 * String password = PropKit.get("password");<br><br>
	 * 
	 * userName = PropKit.use("other_config.txt").get("userName");<br>
	 * password = PropKit.use("other_config.txt").get("password");<br><br>
	 * 
	 * PropKit.use("com/jfinal/config_in_sub_directory_of_classpath.txt");
	 * 
	 * 加载获取property文件.
	 * 数据结构如下:
	 * ConcurrentHashMap
	 * key-->fileName
	 * value-->Properties file {'key1': 'value', 'key2', 'value', ...}
	 * 
	 * @param fileName the properties file's name in classpath or the sub directory of classpath
	 * @param encoding the encoding
	 */
	public static Prop use(String fileName, String encoding) {
		
		Prop result = map.get(fileName);  // 根据fileName从ConcurrentHashMap获取对应的Properties file文件内容
		if ( result == null ) {
			
			result = new Prop(fileName, encoding);  // 加载fileName文件,并将fileName内容保存到Properties中
			
			map.put( fileName, result );  // 将fileName:Properties保存到ConcurrentHashMap中
			if ( PropKit.prop == null ) {
				PropKit.prop = result;
			}
		}
		
		return result;
	}
	
	/**
	 * Using the properties file bye File object. It will loading the properties file if not loading.
	 * 加载获取property文件.
	 * 
	 * @see #use(File, String)
	 */
	public static Prop use(File file) {
		return use( file, Const.DEFAULT_ENCODING );
	}
	
	/**
	 * Using the properties file bye File object. It will loading the properties file if not loading.
	 * <p>
	 * Example:<br>
	 * PropKit.use(new File("/var/config/my_config.txt"), "UTF-8");<br>
	 * Strig userName = PropKit.use("my_config.txt").get("userName");
	 * 
	 * 以文件方式加载获取property文件.
	 * 
	 * @param file the properties File object
	 * @param encoding the encoding
	 */
	public static Prop use(File file, String encoding) {
		
		Prop result = map.get( file.getName() );  // 根据fileName从ConcurrentHashMap获取对应的Properties file文件内容
		if ( result == null ) {
			
			result = new Prop( file, encoding );  // 加载fileName文件,并将fileName内容保存到Properties中
			
			map.put( file.getName(), result );  // 将fileName:Properties保存到ConcurrentHashMap中
			if ( PropKit.prop == null ) {
				PropKit.prop = result;
			}
		}
		return result;
	}
	
	/**
	 * 根据key,清除Properties
	 * 
	 * @param fileName
	 * @return
	 */
	public static Prop useless(String fileName) {
		
		Prop previous = map.remove( fileName );
		
		if ( PropKit.prop == previous ) {
			PropKit.prop = null;
		}
		
		return previous;
	}
	
	/**
	 * 清除所有Properties
	 * 
	 * @param fileName
	 * @return
	 */
	public static void clear() {
		prop = null;
		map.clear();
	}
	
	/**
	 * 获取当前prop对象
	 * 
	 * @return
	 */
	public static Prop getProp() {
		
		if ( prop == null ) {
			throw new IllegalStateException("Load propties file by invoking PropKit.use(String fileName) method first.");
		}
		
		return prop;
	}
	
	/**
	 * 根据文件名(key),获取Properties
	 * 
	 * @param fileName
	 * @return
	 */
	public static Prop getProp(String fileName) {
		return map.get(fileName);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应value值
	 * 
	 * @param fileName
	 * @return
	 */
	public static String get(String key) {
		return getProp().get(key);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应value值,无则返回默认值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static String get(String key, String defaultValue) {
		return getProp().get(key, defaultValue);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应int类型value值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Integer getInt(String key) {
		return getProp().getInt(key);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应int类型value值,无则返回默认int类型值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Integer getInt(String key, Integer defaultValue) {
		return getProp().getInt(key, defaultValue);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应long类型value值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Long getLong(String key) {
		return getProp().getLong(key);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应long类型value值,无则返回默认long类型值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Long getLong(String key, Long defaultValue) {
		return getProp().getLong(key, defaultValue);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应boolean类型value值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Boolean getBoolean(String key) {
		return getProp().getBoolean(key);
	}
	
	/**
	 * 获取当前Prop(Properties)中key属性对应boolean类型value值,无则返回默认boolean类型值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Boolean getBoolean(String key, Boolean defaultValue) {
		return getProp().getBoolean(key, defaultValue);
	}
	
	/**
	 * 判断当前Prop(Properties)中是否包含指定key
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static boolean containsKey(String key) {
		return getProp().containsKey(key);
	}
}


